package cn.jolyoulu.common.core.utils.encryption;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

/**
 * @Author: JolyouLu
 * @Date: 2023/3/18 20:42
 * @Description
 */
@Slf4j
public class AESUtils {

    /**
     * AES 加密算法
     *
     * @param input 原文
     * @param key   密钥（必须16个字节）
     * @param vi    偏移（必须16个字节）
     * @return
     * @throws Exception
     */
    public static String encrypt(String input, String key,String vi) {
        return encrypt(input.getBytes(), key, vi);
    }

    /**
     * AES 解密算法
     *
     * @param input 密文
     * @param key   密钥（必须16个字节）
     * @param vi    偏移（必须16个字节）
     * @return
     * @throws Exception
     */
    public static String decrypt(String input, String key,String vi) {
        return decrypt(input.getBytes(), key, vi);
    }

    /**
     * AES 加密算法
     *
     * @param input 原文
     * @param key   密钥（必须16个字节）
     * @return
     * @throws Exception
     */
    public static String encrypt(String input, String key) {
        return encrypt(input.getBytes(), key, null);
    }

    /**
     * AES 解密算法
     *
     * @param input 密文
     * @param key   密钥（必须16个字节）
     * @return
     * @throws Exception
     */
    public static String decrypt(String input, String key) {
        return decrypt(input.getBytes(), key, null);
    }

    /**
     * AES 加密算法
     *
     * @param input 原文
     * @param key   密钥（必须16个字节）
     * @return
     * @throws Exception
     */
    public static String encrypt(byte[] input, String key) {
        return encrypt(input, key, null);
    }

    /**
     * AES 解密算法
     *
     * @param input 密文
     * @param key   密钥（必须16个字节）
     * @return
     * @throws Exception
     */
    public static String decrypt(byte[] input, String key) {
        return decrypt(input, key, null);
    }

    /**
     * AES 加密算法
     *
     * @param input 原文
     * @param key   密钥（必须16个字节）
     * @param vi    偏移（必须16个字节） null 不校验
     * @return
     * @throws Exception
     */
    public static String encrypt(byte[] input, String key, String vi) {
        Cipher cipher = null;
        try {
            cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
            //创建加密规则 参数1：密钥的字节 参数2：加密类型
            SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(), "AES");
            //进行解密初始化 参数1：选择模式，加密模式/解密模式 参数2：加密规则 参数3：偏移
            if (StringUtils.isNotBlank(vi)) {
                IvParameterSpec iv = new IvParameterSpec(vi.getBytes());
                cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, iv);
            } else {
                cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
            }
            //传入原文字节数值，调用加密方法
            byte[] bytes = cipher.doFinal(input);
            return Base64Utils.urlEncode(bytes);
        } catch (NoSuchAlgorithmException | BadPaddingException | NoSuchPaddingException | IllegalBlockSizeException |
                 InvalidKeyException | InvalidAlgorithmParameterException e) {
            log.error("encrypt", e);
        }
        return null;
    }

    /**
     * AES 解密算法
     *
     * @param input 密文
     * @param key   密钥（必须16个字节）
     * @param vi    偏移（必须16个字节） null 不校验
     * @return
     * @throws Exception
     */
    public static String decrypt(byte[] input, String key, String vi) {
        Cipher cipher = null;
        try {
            cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
            //创建解密规则 参数1：密钥的字节 参数2：加密类型
            SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(), "AES");
            //进行解密初始化 参数1：选择模式，加密模式/解密模式 参数2：加密规则 参数3：偏移
            if (StringUtils.isNotBlank(vi)) {
                IvParameterSpec iv = new IvParameterSpec(vi.getBytes());
                cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, iv);
            } else {
                cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);
            }
            //传入密文字节数值，调用解密方法
            byte[] bytes = cipher.doFinal(input);
            return new String(bytes);
        } catch (NoSuchAlgorithmException | BadPaddingException | NoSuchPaddingException | IllegalBlockSizeException |
                 InvalidKeyException | InvalidAlgorithmParameterException e) {
            log.error("decrypt", e);
        }
        return null;
    }

    public static void main(String[] args) {
        //原文
        String input = "key=1&value=4&";
        //定义密钥（使用AES加密，密钥必须是16字节）
        String key = "8e1291fd6f3d4dde95a7a24819dce1d1";
        System.out.println("<======加密======>");
        String encryptAES = encrypt(input, key);
        System.out.println(encryptAES);
        System.out.println("<======解密======>");
        byte[] decode = Base64Utils.urlDecode(encryptAES.getBytes());
        String decryptAES = decrypt(decode, key);
        System.out.println(decryptAES);
    }

}
